;;;;; ejemplo de imprimir en modo protegido: IMPRIMIR_TEXTO iniciando, 26, 0x0A, 10, 10 ;;;;;;
BITS 16

%include "macrosmodoreal.mac"
%include "macrosmodoprotegido.mac"

%define KORG 0x1200

global start

extern tsss
extern gdt
extern GDT_DESC
extern IDT_DESC
extern inicializar_idt
extern excepciones				;AGREGADO
extern excepciones_len			;AGREGADO
extern inicializar_mmu			;AGREGADO
extern inicializar_dir_kernel	;AGREGADO
extern inicializar_dir_usuario	;AGREGADO
extern extender_dir_kernel  	;AGREGADO
extern pagina_libre_usuario 	;AGREGADO
extern pagina_libre_kernel  	;AGREGADO
extern mapear_pagina			;AGREGADO
extern unmapear_pagina			;AGREGADO
extern cargar_tarea				;AGREGADO
extern cargar_tarea_inicial		;AGREGADO

extern resetear_pic
extern habilitar_pic
extern imprimir_todo			;AGREGADO
extern printf					;AGREGADO

;Aca arranca todo, en el primer byte.
start:
		cli			;no me interrumpan por ahora
		jmp 	bienvenida

;aca ponemos todos los mensajes		
iniciando: db 'Iniciando el kernel del TP'
iniciando_len equ $ - iniciando	
nombre_grupo: db 'The Vibrators',0


bienvenida:
	IMPRIMIR_MODO_REAL iniciando, iniciando_len, 0x07, 0, 0
	
	;Habilitar A20
	call	checkear_A20
	call 	habilitar_A20
	call	checkear_A20
	
	;xchg bx, bx
	
	
; Ejercicio 1:
; - Completar GDT 												++OK!
; - Pasar a MP								 					++OK!
; - Pintar pantalla de negro y hacer recuadro					++OK!
	
	lgdt [GDT_DESC]
	
	mov eax,cr0
	or 	eax, 0x1
	mov cr0, eax
	
	jmp	0x08:modo_protegido
	BITS 32
modo_protegido:	
	; Estamos en modo protegido.
	
	; Seteamos los registros de segmento.
	mov	ax, 0x10
	mov	ds, ax
	mov	fs, ax
	mov gs, ax
	mov ss, ax
	mov ax, 0x18
	mov	es, ax
	
	; Seteamos los registros de la pila.
	mov ebp, 0x19000-4
	mov esp, ebp
	
	xor edi, edi
	xor eax, eax
	mov ecx, 80 * 25
	
	.pintarNegro:
		stosw
		loop .pintarNegro

	xor edi, edi
	add edi, 80 << 1
	mov	ecx, 80
	xor eax, eax
	mov	ah, 0x10				; Fondo azul.
	
	.azulPrimera:
		stosw
		loop .azulPrimera

	xor edi, edi
	add edi, (80 * 23) << 1
	mov	ecx, 80

	.azulUltima:
		stosw
		loop .azulUltima		
		
	;xchg bx, bx	

; Ejercicio 2
; - crear idt para excepciones                            		++OK!
; - generar excepcion											++OK!

	; Creamos idt.
	lidt [IDT_DESC]
	call inicializar_idt

			
	; Generamos excepcion de Division por 0(manual).												
	;mov ebx, 0
	;div ebx
	
	; Generamos excepcion de Page Fault(por instruccion INT).												
	;INT 14
	
	;xchg bx, bx
	
; Ejercicio 3
; - inicializar la mmu																++OK!
; - inicializar el directorio de paginas del kernel h 4mb							++OK!
; - habilitar paginacion															++OK!
; - imprimir mensaje																++OK!
; - habilitar paginas de 4 mb														++OK!
; - modificar el directorio de paginas para mapear h 64mb usando paginas de 4mb		++OK!
; - TODO: ALGO PARA PROBAR QUE ANDA	


	call inicializar_mmu			;inicializamos la mmu.

	call inicializar_dir_kernel		;incializamos el directorio de paginas y las paginas de 4kb.
	mov cr3, eax					;cargamos la direccion del directorio en cr3.

	;xchg bx, bx
	
	mov eax, cr0				
	or  eax, 0x80000000		;habilitamos paginacion.
	mov cr0, eax
	
	; Imprimimos nombre del grupo por pantalla con paginacion activada.
	push 1
	push 0
	push 0x0F
	push nombre_grupo
	call printf
	add esp, 16
	
	;xchg bx, bx	
	
	;;Habilitamos modo extendido (para paginas de 4mb).
	mov eax, cr4
	or eax, 0x10
	mov cr4, eax	
		
	mov eax, cr3	
	and ax, 0xE7
	mov cr3, eax
	
	call extender_dir_kernel	;cargamos las paginas de 4mb.

	;xchg bx, bx	
	
; Ejercicio 4:
; - inicializar_dir_usuario											++OK!
; - mapear_pagina													++OK!
; - intercambiar dir												++OK!
; - pintar primer linea												++OK!
; - volver a intercambiar											++OK!
; - unmapear														++OK!
	
	call inicializar_dir_usuario
	mov ebx, eax	; ebx = proximo cr3.
	
	;void mapear_pagina(unsigned int virtual, unsigned int cr3, unsigned int fisica,unsigned int atributos);
	push 0x3
	push 0xb8000
	push eax
	push 0x1F040000	
	call mapear_pagina
	add esp, 16
	
	mov eax, cr3
	mov esi, eax	;guardo el viejo cr3.
	mov eax, ebx
	mov cr3, eax	;cargo nuevo cr3.	
	mov ebx, esi	;guardamos en ebx el viejo cr3.
	
	;xchg bx, bx
	
	mov edi, 0x1F040000
	mov	ecx, 80	
	xor eax, eax
	mov	ah, 0x2F				; Fondo azul, letra blanca.
	
	.verdePrimera:
		add edi, 1
		mov [edi], ah
		add edi, 1
		loop .verdePrimera

	;xchg bx,bx
	
	mov eax, ebx	;volvemos al cr3 anterior
	mov cr3, eax
	
	;xchg bx,bx
	
	;void unmapear_pagina(unsigned int virtual, unsigned int cr3);
	mov eax, cr3
	push eax
	push 0x1F040000
	call unmapear_pagina
	add esp, 8
	
	;xchg bx,bx

	
; Ejercicio 5
; - completar IDT 88 y 89											++OK!
; - completar IDT reloj y teclado									++OK!
; - habilitar pic e interrupciones para probar.						++OK!
	
	call resetear_pic
	call habilitar_pic
	sti
	
	
; Ejercicio 6
; - cargar_tarea													++OK!					
; - saltar a la tarea 1												++OK!
; - modificar ISR reloj para que cambie de tarea					++OK!
	
	call cargar_tarea_inicial

	;void cargar_tarea(unsigned int desde, unsigned int indice)	
	push 0x1		;indice=1 (tarea 1)
	push 0x10000	;0x10.000
	call cargar_tarea
	add esp, 8
	
	push 0x2		;indice=2 (tarea 2)
	push 0x12000	;0x10.000
	call cargar_tarea
	add esp, 8
	
	push 0x3		;indice=3 (tarea 3)
	push 0x14000	;0x10.000
	call cargar_tarea
	add esp, 8
	
	push 0x4		;indice=4 (tarea 4)
	push 0x16000	;0x10.000
	call cargar_tarea
	add esp, 8
	
	;xchg bx, bx
	
	mov ax, 0x30	;marco la tarea 0 como la actual.
	ltr ax
	
	jmp 0x38:0
	
	
	jmp	$
		
	
		
		
%include "a20.asm"

TIMES 0x2000 - KORG - ($ - $$) db 0x0
